package com.example.sourcesprng.jdk8._stream;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamTest02 {

    public static void main(String[] args) {
        /**
            常用Stream的方法：
                forEach()：遍历
                count()：返回个数
                filter()：过滤
                map()：映射
                concat()：组合
                limit()
                skip()：
                flatMap():map返回的是指定类型，flatMap返回的是stream
                sorted()：排序
                distinct()：去重
                match()：匹配
                max/min：最大值/最小值
                reduce()：归纳一个数据
                mapToInt/mapToDouble/mapToLong
                concat：可以将两个stream()合并为一个，但是只能两两合并
                peek：
                allMatch/anyMatch/noneMatch：
                findFirst/findAny:
                collect()：

         */

        List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8);
        list.forEach(System.out::print);

        long count = list.stream().count();
        System.out.println("stream().count()的结果：" + count);

        List<Integer> integers = list.stream().filter(ints -> ints > 5).toList();
        integers.forEach(System.out::println);

        list.forEach(System.out::print);
        System.out.println();
        List<Integer> integers1 = list.stream().map(key -> {
            if (key <= 5) {
                return key * 5;
            } else {
                return key * 2;
            }
        }).toList();
        integers1.forEach(System.out::print);
        System.out.println();

        List<Integer> integers2 = list.stream().limit(1).toList();
        integers2.forEach(System.out::println);

        List<Integer> integers3 = list.stream().skip(2).toList();
        integers3.forEach(System.out::println);

        // sorted()排序
        List<Integer> integers4 = list.stream().sorted((i1, i2) -> i2 - i1).toList();
        list.forEach(System.out::println);
        integers4.stream().forEach(System.out::println);

        // distinct()去重
        List<String> strList = List.of("AA", "BB", "CC", "AA");
        strList.stream().distinct().forEach(System.out::println);

        List<Integer> intList = List.of(1, 2, 3, 4, 3, 2);
        intList.stream().distinct().forEach(System.out::println);

        BiFunction<String, Integer, User> biFunction = User::new;
        Stream<User> apply = Stream.of(biFunction.apply("张三", 18), biFunction.apply("李四", 20), biFunction.apply("李四", 21));
        apply.distinct().forEach(System.out::println);

        /**
             match():
                allMatch()：全匹配
                anyMatch()：匹配任意一个
                noneMatch()：全不匹配
         */
        int maxCount = 10;
        List<Integer> matchList = List.of(12, 8, 6, 1, -1, -12);
        boolean allMatch = matchList.stream().allMatch(key -> key > maxCount);
        System.out.println(String.format("所有的参数都大于%d => %s", maxCount, allMatch));

        boolean anyMatch = list.stream().anyMatch(key -> key % 2 == 0);
        System.out.println("至少有一个偶数：" + anyMatch);

        boolean noneMatch = list.stream().noneMatch(key -> key > 100);
        System.out.println("全部小于100：" + noneMatch);

        /*
            max/min：
                max：先排序，取最后一个
                min：先排序，取第一个
         */
        List<Integer> maxAndMinList = List.of(-1, 4, 8, 1, 3, -8);
        Optional<Integer> max = maxAndMinList.stream().max((o1, o2) -> o1 - o2);
        System.out.println("当前集合中的最大值为：" + max.get());

        Optional<Integer> min = maxAndMinList.stream().max((o1, o2) -> o2 - o1);
        System.out.println("当前集合的最小值为：" + min.get());

        /*
            reduce
              处理流，最终归纳得到一个数据
              例如：对流中数据进行求和，求最大值，求最小值
         */
        List<Integer> reduceList = List.of(-1, 4, 8, 1, 3, -8);
        Integer maxReduce = reduceList.stream().reduce(0, (x, y) -> x > y ? x : y);
        System.out.println("当前集合中的在最大值为：" + maxReduce);

        // 10：含义是初始值，该初始值会参数逻辑的处理的，所以在逻辑处理时，需要考虑该初始值可能带来的影响
        maxReduce = reduceList.stream().reduce(10, (x, y) -> x > y ? x : y);
        System.out.println("当前集合中的在最大值为：" + maxReduce);

        // 无初始值的方法
        Optional<Integer> minReduce = reduceList.stream().reduce((x, y) -> x > y ? y : x);
        System.out.println("当前集合中的在最小值为：" + minReduce.get());

        Optional<Integer> sumReduce = reduceList.stream().reduce((x, y) -> x + y);
        System.out.println("当前集合的总和为：" + sumReduce.get());

        /*
            map + reduce组合使用：
         */
        List<User> users = List.of(new User("张三", 18), new User("李四", 19), new User("王五", 23));
        Optional<Integer> reduce = users.stream().map(user -> user.getAge()).reduce((x, y) -> x > y ? x : y);
        System.out.println("三个人中，年龄最大的有：" + reduce.get() + "岁");

        /*
            mapToInt
            mapToLong
            mapToDouble
         */
        Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
        integerStream.forEach(System.out::println);

        IntStream intStream = Stream.of(1, 2, 3, 4, 5).mapToInt(key -> key.intValue());
        intStream.forEach(System.out::println);

        IntStream intStream1 = Stream.of(1, 2, 3, 4, 5).mapToInt(Integer::intValue);
        intStream1.forEach(System.out::println);

        /*
            concat(): 合并流，两两合并
         */
        Stream<String> stream1 = Stream.of("a", "b", "c", "d");
        Stream<String> stream2 = Stream.of("d", "e", "f");
        Stream<String> concat = Stream.concat(stream1, stream2);
        concat.forEach(System.out::println);

        /*
            findFirst：返回第一个
            findAny：返回任意一个,一般会返回第一个
         */
        Stream<String> findStream = Stream.of("a", "b", "c");
        Optional<String> first = findStream.findFirst();
        System.out.println("第一个数据为：" + first.get());
        findStream = Stream.of("a", "b", "c");
        Optional<String> any = findStream.findAny();
        System.out.println("随机一个数据为：" + any.get());



    }
}
